#include "head.h"

// 存放文件的真实路径
char path[512] = {0};

int main(int argc , char* argv[])
{

    //读取配置文件
    config  *config_info = (config *)malloc(sizeof(config));
    bzero(config_info,sizeof(config_info));
    int ret = read_config("./config.ini",config_info);
    if(ret == 0) {
        printf("配置文件读取失败\n");
        exit(0);
    }
    puts("配置文件读取完成");
    //初始化日志 
    INIT_LOG(config_info -> log_path);
    

    printf("线程个数: %d\n",config_info -> pthread_count);
    puts("配置文件和日志初始化完成");
    // 初始化
    MYSQL* mysql = NULL;
    int socket_fd = 0;
    pool_data_t pool_data;
    shared_resource_t shared_resource;
    server_init(config_info,&shared_resource, &pool_data, &socket_fd, &mysql);
    free(config_info);
    // epoll配置
    int epoll_fd = epoll_create(10);
    ERROR_CHECK(epoll_fd, -1, "epoll create in server");
    epoll_add(epoll_fd,socket_fd);
    
    // 超时踢出
    hash_map_t hash_map;
    hash_map_init(&hash_map, 11);
    int cur_time = 0;
    timeout_node_t* timeout_queue[TIMEOUT] = {0};
    int epoll_ready_flag = 0;

    long old_time = 0;
    long new_time = 0;
    int  wait_time = 0;
    
    while(1){
        epoll_ready_flag = 0;
        struct epoll_event events[10];
        bzero(events, sizeof(struct epoll_event) * 10);

        struct timeval current_time;
        gettimeofday(&current_time, NULL);
        old_time = current_time.tv_sec * 1000 + current_time.tv_usec / 1000;
        if(wait_time <= 0){
            wait_time = 1000;
        }

        int epoll_num = epoll_wait(epoll_fd, events, 10, wait_time);
        ERROR_CHECK(epoll_num, -1, "epoll wait in server.c");
        if(epoll_num == 0){ epoll_ready_flag = 1;}

        gettimeofday(&current_time, NULL);
        new_time = current_time.tv_sec * 1000 + current_time.tv_usec / 1000;
        wait_time = wait_time - (int)(new_time - old_time);

        for(int i=0; i<epoll_num; i++){
            if (events[i].data.fd == socket_fd)
            {
                // 有三次握手来
                // 把这个网络描述符加入超时踢出队列
                puts("进入accept");
                int net_fd = accept(socket_fd, NULL, NULL);
                ERROR_CHECK(net_fd, -1, "accept in server.c");
                hash_map_add(&hash_map, net_fd, cur_time);
                timeout_add(timeout_queue, net_fd, cur_time); 
                epoll_add(epoll_fd, net_fd);
                continue;
            }
           
            // 这里要更新超时踢出队列 
            int index = 0;
            hash_map_del(&hash_map, events[i].data.fd, &index);
            timeout_del(timeout_queue, events[i].data.fd, index);
            timeout_add(timeout_queue, events[i].data.fd, cur_time);
            hash_map_add(&hash_map, events[i].data.fd, cur_time);

            int ret = require_handler(events[i].data.fd,&shared_resource,mysql,
                                       epoll_fd, &hash_map, timeout_queue);

            if(ret == -1){
                // 这里要把网络文件描述符从超时踢出队列中移除
                int index = 0;
                hash_map_del(&hash_map, events[i].data.fd, &index);
                timeout_del(timeout_queue, events[i].data.fd, index);
                epoll_del(epoll_fd,events[i].data.fd);
                close(events[i].data.fd);
            }
        }

        // 这里是超时队列
        if(epoll_ready_flag){
            cur_time = (cur_time+1) % TIMEOUT;
            //printf("cur_time = %d\n", cur_time);
            timeout_del_index(timeout_queue, cur_time, &hash_map);
        }
    }
    


    return 0; 
}

